﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Data.SqlClient;
using System.Data;
using TSL_Tools.SqlTools;
using ReportingEngine;
using System.IO;
using System.Windows.Forms.DataVisualization.Charting;
using System.Xml;
using System.ComponentModel;
using System.Drawing;

namespace VSLT_Reporting
{
    public partial class MainWindow : Window
    {
        #region -- Core Chart Handler Methods -------------------------------------------------------------------------------------------------
        /// <summary>
        /// Reads the charting XML file and builds the plotColors list to use when making charts.
        /// </summary>
        private void GetChartObjectColorsFromXmlFile()
        {
            try
            {
                XmlDocument xDoc = new XmlDocument();
                xDoc.Load(Properties.Settings.Default.ChartObjectFileName);

                #region -- PlotColors ------------------------------------------------------------------------
                //First build the plot colors list so it can be used going through the iterations
                foreach (XmlNode xNode in xDoc.GetElementsByTagName("PlotColors"))
                {
                    foreach (XmlNode xChild in xNode.ChildNodes)
                    {
                        System.Drawing.Color c = (System.Drawing.Color)TypeDescriptor.GetConverter(typeof(System.Drawing.Color)).ConvertFromString(xChild.Attributes["color"].Value);
                        plotColors.Add(c);
                    }
                }
                #endregion
            }
            catch (XmlException ex)
            {
                MessageBox.Show(ex.ToString());
            }

        }
        
        /// <summary>
        /// This method will initialize the TSL_ChartingDataSeries List if null, or clear it if not null
        /// </summary>
        private void ClearChartObjectList()
        {
            if (chartObjects == null)
            {
                chartObjects = new List<TSL_ChartingDataSeries>();
            }
            else
            {
                chartObjects.Clear();
            }
        }

        /// <summary>
        /// Adds a chart data series to the core chart object in the application
        /// </summary>
        /// <param name="chartObjectId">the index of the TSL_ChartingDataSeries list that contains the charting object</param>
        private void AddChartSeriesItems(int chartObjectId)
        {
            AddChartSeriesItems(chartObjects[chartObjectId]);
        }

        /// <summary>
        /// Adds a chart data series to the core chart object in the application
        /// </summary>
        /// <param name="chartingDataSeries">a TSL_ChartingDataSeries object, which contains all of the settings and data for a series.</param>
        private void AddChartSeriesItems(TSL_ChartingDataSeries chartingDataSeries)
        {
            AddChartSeriesItems(chartingDataSeries, String.Format("Run{0}_{1}", chartingDataSeries.runId, chartingDataSeries.fullCounterName));
        }

        /// <summary>
        /// Adds a chart data series to the core chart object in the application
        /// </summary>
        /// <param name="chartingDataSeries">a TSL_ChartingDataSeries object, which contains all of the settings and data for a series.</param>
        private void AddChartSeriesItems(TSL_ChartingDataSeries chartingDataSeries, string seriesName)
        {
            Chart chart = this.FindName("MyWinformChart") as Chart;
            chart.BackColor = System.Drawing.Color.White;
            chart.BackSecondaryColor = System.Drawing.Color.SkyBlue;
            chart.BackGradientStyle = GradientStyle.TopBottom;
            chart.BorderColor = System.Drawing.Color.Black;
            chart.BorderDashStyle = ChartDashStyle.Solid;
            chart.BorderWidth = 1;

            chart.ChartAreas[0].BackColor = System.Drawing.Color.White;
            chart.ChartAreas[0].BorderColor = System.Drawing.Color.Black;
            chart.ChartAreas[0].BorderDashStyle = ChartDashStyle.Solid;
            chart.ChartAreas[0].BorderWidth = 1;
            chart.ChartAreas[0].ShadowOffset = 3;


            if (chartingDataSeries.chartObjectScale == 1)
            {
                chart.ChartAreas[0].AxisY.Maximum = 100;
            }
            Series series = new Series(seriesName);
            series.ChartType = SeriesChartType.Line;
            series.MarkerStyle = MarkerStyle.Square;
            series.MarkerSize = 3;
            Font font = new Font("Microsoft Sans Serif", 36, System.Drawing.FontStyle.Regular, GraphicsUnit.Point);
            series.Font = font;

            chart.Series.Add(series);
            int x = chart.Series.Count - 1;
            chart.Series[x].XValueMember = "Test Time";
            chart.Series[x].YValueMembers = "ComputedValue";
            chart.Series[x].Points.DataBindXY(chartingDataSeries.GetTestIntervalKeysForCharting(), chartingDataSeries.GetTestIntervalValuesForCharting());
            chart.DataManipulator.InsertEmptyPoints(chartingDataSeries.intervalSpan, IntervalType.Number, chart.Series[x]);
            chart.Series[x].Color = chartingDataSeries.lineColor;

        }
        #endregion

        #region -- Test Avg Time Reporting Chart Stuff ----------------------------------------------------------------------------
        private void AddCoreTestCaseTableAndChartToReport()
        {
            DateTime dt = DateTime.Now;
            // ----- Get the data to build table and chart -----
            DataTable _table = new DataTable();
            GenerateRunData(TSL_ReportingEngine.Sql_SUMMARY_TESTRESULTS, ref _table, true, "Test Name");
            
            // THIS BUILDS THE CHART AND PASTES IT INTO THE DOCUMENT
            BuildTestTimingChart(ref _table);
            // This builds the table that acts as a legend and a summary
            _table.Columns.Remove("TestNameWithId");
            
            for(int x = 0; x < _table.Rows.Count; x++)
            {
                _table.Rows[x]["Name"] = String.Format("<{0}>: {1}", _table.Rows[x]["ScenarioName"], _table.Rows[x]["Name"]);
            }
            _table.Columns.Remove("ScenarioName");
            FlowDocument flowDocTemp = CreateXamlChartTableFromDataTable("Test Timings", _table, new List<int>(new int[] { 326, 38, 38, 38, 38, 38, 38, 38, 38, 38 }));

            rtbResults.Document.Blocks.Add(flowDocTemp.Blocks.FirstBlock);
            rtbResults.UpdateLayout();

            //AddDebugTimingInfo((TimeSpan)(DateTime.Now - dt), " -- AddCoreTestCaseTableAndChartToReport");
        }

        private void BuildTestTimingChart(ref DataTable testItems)
        {
            tsslMessage.Content = String.Format("Building Test Timing Chart");

            Chart chart = this.FindName("MyWinformChart") as Chart;
            LoadChartTemplate(ref chart, Properties.Settings.Default.ChartTemplateName);
            chart.Titles[0].Text = Msg_CHART_TESTTIMETITLE;
            ClearChartObjectList();

            AddDebugTimingInfo(GetCoreTestChartObjects(ref testItems), " -- GetCoreTestChartObjects Total Time");

            /*
<!--<Annotations>
    <RectangleAnnotation _Template_="0" BackColor="128,255,128" Text="Good" ClipToChartArea="ChartArea1" IsSizeAlwaysRelative="False" X="0" Y="0" Width="50" Height="20" TextStyle="Shadow" AxisXName="ChartArea1\rX" YAxisName="ChartArea1\rY" AnchorAlignment="BottomLeft">
    </RectangleAnnotation>
    <RectangleAnnotation _Template_="1" BackColor="255, 255, 0" Text="Marginal" ClipToChartArea="ChartArea1" IsSizeAlwaysRelative="False" X="0" Y="20" Width="50" Height="40" TextStyle="Shadow" AxisXName="ChartArea1\rX" YAxisName="ChartArea1\rY" AnchorAlignment="BottomLeft">
    </RectangleAnnotation>
    <RectangleAnnotation _Template_="2" BackColor="255, 128, 64" Text="Poor" ClipToChartArea="ChartArea1" IsSizeAlwaysRelative="False" X="0" Y="60" Width="50" Height="40" AxisXName="ChartArea1\rX" YAxisName="ChartArea1\rY">
    </RectangleAnnotation>
  </Annotations>-->            
            */

            //RectangleAnnotation _rectAnn = new RectangleAnnotation();
            //_rectAnn.BackColor = System.Drawing.Color.Green;
            //_rectAnn.Text = "Good";
            //_rectAnn.ClipToChartArea = "ChartArea1";
            //_rectAnn.IsSizeAlwaysRelative = false;
            //_rectAnn.X = 0;
            //_rectAnn.Y = 0;
            //_rectAnn.Width = 0;
            //_rectAnn.Height = 0;
            //_rectAnn.AxisX.Name = "ChartArea1\rX";
            //_rectAnn.AxisY.Name = "ChartArea1\rY";
            //chart.Annotations.Add(_rectAnn);


            AddCurrentChartToReport();
        }
        
        private TimeSpan GetCoreTestChartObjects(ref DataTable testItems)
        {
            DateTime dt = DateTime.Now;
            string sqlConn = Properties.Settings.Default.sqlConn;
            currentPlotColor = 0;

            // Name	                        Passed	Minimum	Average	Maximum	Std Dev	90Percent	95Percent
            // Single Project_ViewAll_OFF	150	    154.41	166.71	185.54	6.67	175.94	    179.55
            for (int x = 0; x < testItems.Rows.Count; x++)
            {
                string sqlCmd = String.Format(TSL_ReportingEngine.Sql_GETPERFMON_TESTCASESAMPLES, currentlyHighlightedRunId, testItems.Rows[x]["TestNameWithId"].ToString());
                DataTable _table;
                TimeSpan ts = tts.ExecuteReaderTable(sqlCmd, out _table);
                AddDebugTimingInfo(ts, " --\tCoreTestChartObjects " + sqlCmd);
                mostRecentSqlQuery = sqlCmd;

                TSL_ChartingDataSeries series = new TSL_ChartingDataSeries();
                series.runId = currentlyHighlightedRunId;
                series.fullCounterName = String.Format("{0}_{1}", testItems.Rows[x]["Name"], x);
                series.name = "Avg. Test Time";
                series.machineName = re.listOfRuns[currentlyHighlightedRunId].controllerName;
                series.categoryName = "LoadTest:Test";
                series.counterName = "Avg. Test Time";
                series.instanceName = "_Total";
                //series.lineColor = System.Drawing.Color.LightYellow;
                series.lineColor = plotColors[currentPlotColor % plotColors.Count];
                series.chartObjectScale = 0;
                series.intervalSpan = re.listOfRuns[currentlyHighlightedRunId].sampleRate;
                currentPlotColor++;
                series.minValue = (decimal)testItems.Rows[x]["Min"];
                series.averageValue = (decimal)testItems.Rows[x]["Avg"];
                series.maxValue = (decimal)testItems.Rows[x]["Max"];
                series.stdDev = (decimal)testItems.Rows[x]["StdDev"];
                series.ninetyPct = (decimal)testItems.Rows[x]["90%"];
                series.ninetyFivePct = (decimal)testItems.Rows[x]["95%"];
                series.testIntervalValues = _table.Copy();
                AddChartSeriesItems(series);
            }

            return (TimeSpan)(DateTime.Now - dt);
        }
        #endregion

        #region -- Transaction Avg Time Reporting Chart Stuff ----------------------------------------------------------------------------
        private void AddCoreTransactionTableAndChartToReport()
        {
            if (re.listOfRuns[currentlyHighlightedRunId].resultTypes.HasFlag(ResultTypesStoredInLoadTest.ContainsTransactions))
            {
                DateTime dt = DateTime.Now;
                // ----- Get the data to build table and chart -----
                DataTable _table = new DataTable();
                GenerateRunData(TSL_ReportingEngine.Sql_SUMMARY_TRANSACTIONRESULTS, ref _table, true, "Transaction Name");
                //        // remove the "ID" column from the table
                if (_table.Columns.Contains("Id"))
                {
                    _table.Columns.Remove("Id");
                }

                // THIS BUILDS THE CHART AND PASTES IT INTO THE DOCUMENT
                BuildTransactionTimingChart(ref _table);
                
                // This builds the table that acts as a legend and a summary
                if (_table.Columns.Contains("TransactionNameWithId"))
                {
                    _table.Columns.Remove("TransactionNameWithId");
                }
                
                // This part is commented out because the current DB schema only allows a 64 character name. The below errors too much.
                //for (int x = 0; x < _table.Rows.Count; x++)
                //{
                //    _table.Rows[x]["Name"] = String.Format("<{0}:{1}>: {2}", _table.Rows[x]["ScenarioName"], _table.Rows[x]["TestCaseName"], _table.Rows[x]["Name"]);
                //}
                _table.Columns.Remove("ScenarioName");
                _table.Columns.Remove("TestCaseName");
                FlowDocument flowDocTemp = CreateXamlChartTableFromDataTable("Transaction Timings", _table, new List<int>(new int[] { 326, 38, 38, 38, 38, 38, 38, 38, 38, 38 }));

                rtbResults.Document.Blocks.Add(flowDocTemp.Blocks.FirstBlock);
                rtbResults.UpdateLayout();
            }
        }

        private void BuildTransactionTimingChart(ref DataTable transactionItems)
        {
            // TODO: Add Chart initialization info here
            tsslMessage.Content = String.Format("Building Transaction Timing Chart");

            Chart chart = this.FindName("MyWinformChart") as Chart;
            LoadChartTemplate(ref chart, Properties.Settings.Default.ChartTemplateName);
            chart.Titles[0].Text = Msg_CHART_TRANSACTIONTIMETITLE;
            ClearChartObjectList();

            AddDebugTimingInfo(GetCoreTransactionChartObjects(ref transactionItems), " -- GetCoreTransactionChartObjects Total Time");
            AddCurrentChartToReport();
        }

        private TimeSpan GetCoreTransactionChartObjects(ref DataTable transactionItems)
        {
            DateTime dt = DateTime.Now;
            string sqlConn = Properties.Settings.Default.sqlConn;
            currentPlotColor = 0;

            //Name	    Total	Minimum	Average	Maximum	Std Dev	90Percent	95Percent
            //HomePage	150	    10.94	19.96	34.27	4.63	25.50	    29.09            
            for (int x = 0; x < transactionItems.Rows.Count; x++)
            {
                string sqlCmd = String.Format(TSL_ReportingEngine.Sql_GETPERFMON_TRANSACTIONSAMPLES, currentlyHighlightedRunId, transactionItems.Rows[x]["TransactionNameWithId"].ToString());
                DataTable _table;
                TimeSpan ts = tts.ExecuteReaderTable(sqlCmd, out _table);
                AddDebugTimingInfo(ts, " --\tCoreTransactionChartObjects " + sqlCmd);
                mostRecentSqlQuery = sqlCmd;

                TSL_ChartingDataSeries series = new TSL_ChartingDataSeries();
                series.runId = currentlyHighlightedRunId;
                series.fullCounterName = String.Format("{0}_{1}", transactionItems.Rows[x]["Name"], x);
                series.name = "Avg. Transaction Time";
                series.machineName = re.listOfRuns[currentlyHighlightedRunId].controllerName;
                series.categoryName = "LoadTest:Transaction";
                series.counterName = "Avg. Transaction Time";
                series.instanceName = "_Total";
                series.lineColor = plotColors[currentPlotColor % plotColors.Count];
                series.chartObjectScale = 0;
                series.intervalSpan = re.listOfRuns[currentlyHighlightedRunId].sampleRate;
                currentPlotColor++;
                series.testIntervalValues = _table.Copy();
                AddChartSeriesItems(series);
            }

            return (TimeSpan)(DateTime.Now - dt);
        }
        #endregion

        #region -- Page Avg Time Reporting Chart Stuff -----------------------------------------------------------------------------------
        private void AddCorePageTableAndChartToReport()
        {
            if (re.listOfRuns[currentlyHighlightedRunId].resultTypes.HasFlag(ResultTypesStoredInLoadTest.ContainsPages))
            {
                DateTime dt = DateTime.Now;
                // ----- Get the data to build table and chart -----
                DataTable _table = new DataTable();
                GenerateRunData(TSL_ReportingEngine.Sql_SUMMARY_PAGERESULTS, ref _table, true, "Page Name");
                //        // remove the "ID" column from the table
 //               _table.Columns.RemoveAt(0);

                // THIS BUILDS THE CHART AND PASTES IT INTO THE DOCUMENT
                BuildPageTimingChart(ref _table);
                
                if (_table.Columns.Contains("Id"))
                {
                    _table.Columns.Remove("Id");
                }
                // This builds the table that acts as a legend and a summary
                FlowDocument flowDocTemp = CreateXamlChartTableFromDataTable("Page Timings", _table, new List<int>(new int[] { 326, 38, 38, 38, 38, 38, 38, 38, 38, 38 }));
                rtbResults.Document.Blocks.Add(flowDocTemp.Blocks.FirstBlock);
                rtbResults.UpdateLayout();
            }
        }

        private void BuildPageTimingChart(ref DataTable pageItems)
        {
            // TODO: Add Chart initialization info here
            tsslMessage.Content = String.Format("Building Page Timing Chart");

            Chart chart = this.FindName("MyWinformChart") as Chart;
            LoadChartTemplate(ref chart, Properties.Settings.Default.ChartTemplateName);
            chart.Titles[0].Text = Msg_CHART_PAGETIMETITLE;
            ClearChartObjectList();

            AddDebugTimingInfo(GetCorePageChartObjects(ref pageItems), " -- GetCorePageChartObjects Total Time");
            AddCurrentChartToReport();
        }

        private TimeSpan GetCorePageChartObjects(ref DataTable pageItems)
        {
            DateTime dt = DateTime.Now;
            string sqlConn = Properties.Settings.Default.sqlConn;
            currentPlotColor = 0;

            //Name	    Total	Minimum	Average	Maximum	Std Dev	90Percent	95Percent
            //HomePage	150	    10.94	19.96	34.27	4.63	25.50	    29.09            
            for (int x = 0; x < pageItems.Rows.Count; x++)
            {
                string sqlCmd = String.Format(TSL_ReportingEngine.Sql_GETPERFMON_PAGESAMPLES, currentlyHighlightedRunId, pageItems.Rows[x]["Name"].ToString(), pageItems.Rows[x]["Id"].ToString());
                DataTable _table;
                TimeSpan ts = tts.ExecuteReaderTable(sqlCmd, out _table);
                AddDebugTimingInfo(ts, " --\tCorePageChartObjects " + sqlCmd);
                mostRecentSqlQuery = sqlCmd;

                TSL_ChartingDataSeries series = new TSL_ChartingDataSeries();
                series.runId = currentlyHighlightedRunId;
                series.fullCounterName = String.Format("{0}_{1}", pageItems.Rows[x][1], x);
                series.name = "Avg. Page Time";
                series.machineName = re.listOfRuns[currentlyHighlightedRunId].controllerName;
                series.categoryName = "LoadTest:Page";
                series.counterName = "Avg. Page Time";
                series.instanceName = "_Total";
                series.lineColor = plotColors[currentPlotColor % plotColors.Count];
                series.chartObjectScale = 0;
                series.intervalSpan = re.listOfRuns[currentlyHighlightedRunId].sampleRate;
                currentPlotColor++;
                series.testIntervalValues = _table.Copy();
                AddChartSeriesItems(series);
            }

            return (TimeSpan)(DateTime.Now - dt);
        }
        #endregion

        #region -- Perfmon Avg Time Reporting Chart Stuff ----------------------------------------------------------------------------

        private void AddPerfmonInstanceToTable(string machineName, string category, string counter, string instance)
        {
            //Sql_GETINSTANCEIDFROMINSTANCENAMEVIEW
            //NOTE Use the GetChartObjectsFromXmlFile here to build the list.
        }
        
        private void AddPerfmonTableAndChartToReport(string chartTitle, int instanceId, int runId)
        {
            DateTime dt = DateTime.Now;
            // ----- Get the data to build table and chart -----
            DataTable _table = new DataTable();


            // THIS BUILDS THE CHART AND PASTES IT INTO THE DOCUMENT
            BuildPerfmonTimingChart(ref _table, chartTitle);
            // This builds the table that acts as a legend and a summary

            //for (int x = 0; x < _table.Rows.Count; x++)
            //{
            //    _table.Rows[x]["Name"] = String.Format("<{0}>: {1}", _table.Rows[x]["ScenarioName"], _table.Rows[x]["Name"]);
            //}
            //_table.Columns.Remove("ScenarioName");

            //FlowDocument flowDocTemp = CreateXamlChartTableFromDataTable("Test Timings", _table, new List<int>(new int[] { 326, 38, 38, 38, 38, 38, 38, 38, 38, 38 }));

            //rtbResults.Document.Blocks.Add(flowDocTemp.Blocks.FirstBlock);
            //AddSeparatorLineToReport(1);

            rtbResults.UpdateLayout();

            //AddDebugTimingInfo((TimeSpan)(DateTime.Now - dt), " -- AddCoreTestCaseTableAndChartToReport");
        }

        private void BuildPerfmonTimingChart(ref DataTable perfmonItems, string chartTitle)
        {
            tsslMessage.Content = String.Format("Building Perfmon Timing Chart");

            Chart chart = this.FindName("MyWinformChart") as Chart;
            LoadChartTemplate(ref chart, Properties.Settings.Default.ChartTemplateName);
            chart.Titles[0].Text = chartTitle;
            ClearChartObjectList();

            AddDebugTimingInfo(GetCorePerfmonChartObjects(ref perfmonItems), " -- GetCorePerfmonChartObjects Total Time");
            int x = chart.Series.Count;
            chart.Height = chart.Height + (x * Properties.Settings.Default.Charting_LegendRowHeight);
            AddCurrentChartToReport();
        }

        private TimeSpan GetCorePerfmonChartObjects(ref DataTable perfmonItems)
        {
            DateTime dt = DateTime.Now;
            string sqlConn = Properties.Settings.Default.sqlConn;
            currentPlotColor = 0;

            // Name	                        Passed	Minimum	Average	Maximum	Std Dev	90Percent	95Percent
            // Single Project_ViewAll_OFF	150	    154.41	166.71	185.54	6.67	175.94	    179.55
            for (int x = 0; x < perfmonItems.Rows.Count; x++)
            {
                string sqlQuery = @"
SELECT ComputedValue, CAST((SampleTimeStamp - @offset) / 10000000 AS INT) AS [Page Time]  
FROM LoadTestPerformanceCounterSample WHERE LoadTestRunId = {0}
AND InstanceId = {1} ORDER BY [Page Time] ASC
";
                string sqlCmd = String.Format(sqlQuery, currentlyHighlightedRunId, perfmonItems.Rows[x]["instanceId"].ToString());
                DataTable _table;
                TimeSpan ts = tts.ExecuteReaderTable(sqlCmd, out _table);
                AddDebugTimingInfo(ts, " --\tCorePerfmonChartObjects " + sqlCmd);
                mostRecentSqlQuery = sqlCmd;

                TSL_ChartingDataSeries series = new TSL_ChartingDataSeries();
                series.runId = currentlyHighlightedRunId;
                series.fullCounterName = String.Format("{0}_{1}", perfmonItems.Rows[x]["Name"], x);
                series.name = perfmonItems.Rows[x]["Name"].ToString();
                series.machineName = perfmonItems.Rows[x]["machineName"].ToString();
                series.categoryName = perfmonItems.Rows[x]["categoryName"].ToString();
                series.counterName = perfmonItems.Rows[x]["counterName"].ToString();
                series.instanceName = perfmonItems.Rows[x]["instanceName"].ToString();
                series.lineColor = plotColors[currentPlotColor % plotColors.Count];
                series.chartObjectScale = 0;
                series.intervalSpan = re.listOfRuns[currentlyHighlightedRunId].sampleRate;
                currentPlotColor++;
                series.minValue = (decimal)perfmonItems.Rows[x]["Min"];
                series.averageValue = (decimal)perfmonItems.Rows[x]["Avg"];
                series.maxValue = (decimal)perfmonItems.Rows[x]["Max"];
                series.stdDev = (decimal)perfmonItems.Rows[x]["StdDev"];
                series.ninetyPct = (decimal)perfmonItems.Rows[x]["90%"];
                series.ninetyFivePct = (decimal)perfmonItems.Rows[x]["95%"];
                series.testIntervalValues = _table.Copy();
                AddChartSeriesItems(series);
            }

            return (TimeSpan)(DateTime.Now - dt);
        }
        #endregion

    }

    public enum ChartCategory
    {
        CoreMetric = 1,
        SutMachine = 2,
        RigMachine = 3,
        ComboMetric = 4,
        ScorecardMetric = 5
    };

}
